using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.XPath;
using System.Xml;
using System.IO;

namespace CodePlex.Resourceful.Examples
{
    public static class AstoriaExample
    {

        public static void Run()
        {

            AstoriaClient client = new AstoriaClient(new Uri("http://astoria.sandbox.live.com/northwind/northwind.rse"));
            client.Tracer.AddListener(TraceTextWriter.Instance);

            //foreach (string entitySet in client.EntitySets)
            //{
            //    Console.WriteLine(entitySet);
            //}


            //foreach (Entity entity in client.Get("Categories", "CategoryName ne 'Beverages'"))
            //{
            //    Console.WriteLine("{0} {1}",entity.Uri,
            //        entity.Get<int>("CategoryID"),
            //        entity.Get<string>("CategoryName")
                    
            //        );

               
            //}

            ClientResponse response = client.Get(Query.Of("Customers").WhereEqual("ContactTitle","Owner").Top(10).OrderBy("City desc,CompanyName").Format("rdf"));

            Utils.PrettyPrint(response.AsXmlDocument(), Console.Out);


            Utils.Prompt();

        }



        private class AstoriaClient : Client
        {
            public AstoriaClient(Uri rootUri) : base(rootUri) { }

            public IEnumerable<string> EntitySets
            {
                get
                {
                    return Utils.ConvertAll<XmlNode, string>(
                        this.GetRepresentation("").AsXmlDocument().SelectNodes("//DataService[1]/*[1]/*"),
                        delegate(XmlNode item)
                        {
                            return item.Name;
                        });
                }
            }


            public IEnumerable<Entity> Get(string entitySet)
            {
                return this.Get(entitySet, null);
            }

            public IEnumerable<Entity> Get(string entitySet, string predicate)
            {

                string resource = "/" + entitySet;
                if (predicate != null)
                {
                    resource += "[" + Utils.UrlEncode(predicate) + "]";
                }

                return Utils.ConvertAll<XmlNode, Entity>(
                    this.GetRepresentation(resource).AsXmlDocument().SelectNodes("//DataService[1]/*[1]/*"),
                    delegate(XmlNode item)
                    {
                        return new Entity(item);
                    });


            }

            public ClientResponse Get(Query query)
            {
                return this.GetRepresentation(query.ToResource());
            }

        }

        private class Entity
        {
            private readonly XmlNode _node;
            public Entity(XmlNode node)
            {
                _node = node;
            }

            public string Uri
            {
                get
                {
                    return _node.Attributes["uri"].Value;
                }
            }

            public T Get<T>(string name)
            {
                return Utils.ChangeType<T>(_node.SelectSingleNode(name).InnerText);
            }

        }



        private class Query
        {
            private string _entitySet;
            private string _orderby;
            private int? _top;
            private int? _skip;
            private string _format;
            private string _pred;


            private Query() {}
            private Query(Query other) 
            {
                _entitySet = other._entitySet;
                _top = other._top;
                _orderby = other._orderby;
                _skip = other._skip;
                _format = other._format;
                _pred = other._pred;

            }
            public static Query Of(string entitySet) 
            {
                Query rt = new Query();
                rt._entitySet = entitySet;
                return rt;
            }


            public Query WhereEqual(string name, string value)
            {
                Query rt = new Query(this);
                rt._pred = string.Format("{0} eq '{1}'", name, value);
                return rt;
            }


            public Query Top(int top)
            {
                Query rt = new Query(this);
                rt._top = top;
                return rt;
            }
            public Query Skip(int skip)
            {
                Query rt = new Query(this);
                rt._skip = skip;
                return rt;
            }



            public Query OrderBy(string orderby)
            {
                Query rt = new Query(this);
                rt._orderby = orderby;
                return rt;
            }

            public Query Format(string format)
            {
                Query rt = new Query(this);
                rt._format = format;
                return rt;
            }


            public string ToResource()
            {
                StringBuilder path = new StringBuilder();
                path.Append("/" + _entitySet);

                if (_pred != null)
                {
                    path .Append( "[" +Utils.UrlEncode( _pred) + "]");
                }

                NameValuePairs query = new NameValuePairs();


                if (_top != null)
                {
                    query["$top"] = _top.ToString();
                }
                if (_skip != null)
                {
                    query["$skip"] = _skip.ToString();
                }
                if (_orderby != null)
                {
                    query["$orderby"] = _orderby;
                }
                if (_format != null)
                {
                    query["$format"] = _format;
                }

                return Utils.EncodeUrlPath(path.ToString(), query);
            }

           
        }













    }
}
